package com.teamblueplus.comicmaker;

import java.util.ArrayList;

import com.teamblueplus.brush.PaintBrush;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * ComicSurfaceView contains the surfaceview canvas for images and drawing to be
 * added.
 * 
 * @author qui
 * 
 */
public class ComicSurfaceView extends SurfaceView implements
		SurfaceHolder.Callback {

	String TAG = "mySurfaceView"; // tag for logging
	private ComicDrawThread myThread;
	private Context mContext;
	boolean surfaceCreated = false;
	boolean isResize = false;

	// for touching events
	int touchX, touchY;
	float initialDistance, currentDistance;
	float distX, distY;
	private boolean setBackgroundImg = false;
	private String backgroundPath;

	ArrayList<DrawingLayer> savedLayerArray;

	// brush functionality
	private int isBrushOn;
	public PaintBrush brush2;

	public ComicSurfaceView(Context context, AttributeSet attrs) {
		super(context, attrs);
		getHolder().addCallback(this);
		mContext = context;
		myThread = new ComicDrawThread(getHolder(), mContext);
		
		//
		myThread.drawImageBackground = this.setBackgroundImg;
		setFocusable(true);

		savedLayerArray = new ArrayList<DrawingLayer>();

		// brush functionality
		// brush is disable at first
		isBrushOn = 0;
		brush2 = new PaintBrush();

	}

	/**
	 * Fetches the animation thread
	 * 
	 * @return the animation thread
	 */
	public ComicDrawThread getThread() {
		return myThread;
	}
	
	public void setBackgroundImage(String path, boolean setBackground){
		this.backgroundPath = path;
		this.myThread.background = BitmapFactory.decodeFile(path);
		this.setBackgroundImg = setBackground;
		this.myThread.drawImageBackground = setBackground;
		
	}

	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width,
			int height) {
		// TODO Auto-generated method stub

		// this line is important, else brush will not be draw
		// I don't know whats the reason, need to find out
		Log.d("###", "surfaceChange + mBitmap created");
		myThread.mBitmap = Bitmap.createBitmap(width, height,
				Bitmap.Config.ARGB_8888);
		;
	}

	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		if (myThread.getState() == Thread.State.TERMINATED) {
			myThread = new ComicDrawThread(getHolder(), mContext);
		}
		myThread.setLayerArray(savedLayerArray);

		// set the brush array to thread
		myThread.setBrushArray(brush2);
		//sets the background image, if comicmaker activity was called from view comic
		this.myThread.background = BitmapFactory.decodeFile(this.backgroundPath);
		myThread.drawImageBackground = this.setBackgroundImg;
		myThread.setRunning(true);
		myThread.start();
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		// we have to tell thread to shut down & wait for it to finish, or else
		// it might touch the Surface after we return and explode
		boolean retry = true;
		savedLayerArray = myThread.getLayerArray();

		myThread.setRunning(false);

		while (retry) {
			try {
				myThread.join();
				retry = false;
			} catch (InterruptedException e) {
				// we will try it again and again...
			}
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		// call brush event handler
		paintBrush2(event);

		switch (event.getAction() & MotionEvent.ACTION_MASK) {

		case MotionEvent.ACTION_DOWN:
			touchX = (int) event.getX();
			touchY = (int) event.getY();

			// get the layer, save the touch
			myThread.handleActionDown(touchX, touchY);
			
			break;

		case MotionEvent.ACTION_POINTER_DOWN:
			Log.d("finger down", "pinch zoom");
			if (myThread.isTouched()) {
				isResize = true;
				distX = event.getX(0) - event.getX(1);
				distY = event.getY(0) - event.getY(1);
				initialDistance = FloatMath.sqrt(distX * distX + distY * distY);
			}
			break;

		// end 2 fingers
		case MotionEvent.ACTION_POINTER_UP:
			if (myThread.isTouched()) {
				myThread.setTouched(false);
			}
			isResize = false;
			myThread.setNewLayerSize();
			break;

		case MotionEvent.ACTION_MOVE:
			// the gestures

			if (isBrushOn == 0 && myThread.isTouched()) {
				// get the selected layer index
				int selectedLayer = myThread.getSelectedLayer();
				int dragX = (int) event.getX();
				int dragY = (int) event.getY();

				// resizing
				if (isResize) {
					// Get the current distance
					distX = event.getX(0) - event.getX(1);
					distY = event.getY(0) - event.getY(1);
					currentDistance = FloatMath.sqrt(distX * distX + distY
							* distY);

					myThread.resizeLayer(initialDistance, currentDistance);

					// the layer was picked up and is being dragged
				} else {

					int xAmount = dragX - touchX;
					int yAmount = dragY - touchY;

					myThread.moveLayerBy(selectedLayer, xAmount, yAmount);
				}
			}
			break;

		case MotionEvent.ACTION_UP:
			// touch was released
			if (myThread.isTouched()) {
				myThread.setTouched(false);
			}
			break;
		}

		return true;
	}

	// brush functionality
	// event handler for brush
	public void paintBrush2(MotionEvent motionEvent) {

		if (this.isBrushOn == 1) {

			int x = (int) motionEvent.getX();
			int y = (int) motionEvent.getY();

			if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
				this.myThread.brush2.touch_start(x, y);

			} else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
				this.myThread.brush2.touch_move(x, y);

			} else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
				this.myThread.brush2.touch_up();

			}
		}
	}
	
	public void undoBrush(){
		this.brush2.undoBrushStroke();
	}

	public void toggleBrush() {
		Log.d("####", "toggle brush");
		// flip the value of brush
		isBrushOn = isBrushOn ^ 1;
	}

	public int getBrushMode() {
		return isBrushOn;
	}

	public void setResize(boolean bool) {
		isResize = bool;
	}

	public void pause() {
		myThread.setRunning(false);
		while (true) {
			try {
				myThread.join();
			} catch (InterruptedException e) {
				Log.v("pause()", e.toString());
			}
			break;
		}

	}

	public void resume() {

	}

}